package com.pushtime.service.lib;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.pushtime.config.Constants;
import com.pushtime.service.dto.JhipsterDTO;
import com.pushtime.service.dto.YeomanDTO;
import com.pushtime.service.dto.yeoman.GeneratorJhipster;
import com.pushtime.service.lib.engine.KeyWordTemplate;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import java.io.*;
import java.util.Objects;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

@Service
public class PtEngine {

    @Value("${application.generator.project}")
    private String projectPath;
    private final ObjectMapper objectMapper;
    private YeomanDTO yeomanDTO = null;
    private Pattern pattern = null;
    private final String templatePath;
    private final KeyWordTemplate keyWordTemplate;

    public PtEngine(ObjectMapper objectMapper, KeyWordTemplate keyWordTemplate) {
        this.objectMapper = objectMapper;
        this.keyWordTemplate = keyWordTemplate;
        this.templatePath = Objects.requireNonNull(Thread.currentThread().
                getContextClassLoader().getResource(Constants.TEMPLATE_DIR)).getPath();
    }

    /**
     * 生成 jhipster 对象
     *
     * @param jhipsterDTO jhipster 提供的生成信息
     * @param pack 包名
     * @param path 类名/模板名[不包括后缀]
     */
    @SuppressWarnings("deprecation")
    public void generate(JhipsterDTO jhipsterDTO, String pack, String path) throws IOException {
        init();
        GeneratorJhipster generatorJhipster = yeomanDTO.getGeneratorJhipster();
        // 读取模板文件
        String templateUrl = templatePath + Constants.SPLIT + pack + Constants.DOT + Constants.TEMPLATE_SUFFIX;
        FileReader fileReader = new FileReader(templateUrl);
        BufferedReader bufferedReader = new BufferedReader(fileReader);
        // 写入 java 代码
        String codePathUrl = projectPath + Constants.SPLIT + Constants.JAVA_PATH + Constants.SPLIT
                + generatorJhipster.getPackageFolder() + Constants.SPLIT + pack.replace('.', '/') + Constants.SPLIT
                + Constants.GENERATE_DIR;
        File codePath = new File(codePathUrl);
        if (!codePath.exists()) {
            codePath.mkdirs();
        }
        String codeUrl = codePathUrl + Constants.SPLIT
                + jhipsterDTO.getName() + Constants.GENERATE_SUFFIX + path
                + Constants.DOT + Constants.JAVA_SUFFIX;
        FileWriter fileWriter = new FileWriter(codeUrl);
        BufferedWriter bufferedWriter = new BufferedWriter(fileWriter);
        String line;
        // 读取模板内容
        while ((line = bufferedReader.readLine()) != null) {
            Matcher matcher = pattern.matcher(line);
            while (matcher.find()) {
                String group = matcher.group();
                matcher = keyWordTemplate.replace(pattern, matcher, jhipsterDTO, yeomanDTO, group);
            }
            String result = matcher.replaceFirst("");
            bufferedWriter.write(result);
            bufferedWriter.newLine();
        }
        bufferedReader.close();
        bufferedWriter.close();
    }

    /**
     * 初始化 yeoman 配置文件
     *
     * @throws IOException 抛出IO异常：读取文件失败
     */
    private void init() throws IOException {
        if (yeomanDTO == null) {
            // 初始化配置文件
            String yorcPath = projectPath + Constants.SPLIT + Constants.YORC_PATH;
            File yorcFile = new File(yorcPath);
            yeomanDTO = objectMapper.readValue(yorcFile, YeomanDTO.class);
        }
        if (pattern == null) {
            pattern = Pattern.compile(Constants.REGIX);
        }
    }
}
